package com.snake.win.web;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.net.SocketHints;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class Client {
    Socket socket;
    String host = "localhost";
    int port = 12345;
    private PrintWriter writer;
    private BufferedReader reader;
    private Thread listeningThread;
    private boolean connected = false;
    private MessageListener messageListener; // Callback interface

    // Interface for handling received messages
    public interface MessageListener {
        void onMessageReceived(String message);
        void onDisconnected();
    }

    public void connect(MessageListener listener) {
        if (connected) {
            Gdx.app.log("Client", "Already connected.");
            return;
        }
        this.messageListener = listener;
        try {
            SocketHints socketHints = new SocketHints();
            // Set any specific hints if needed
            socket = Gdx.net.newClientSocket(Net.Protocol.TCP, host, port, socketHints);
            writer = new PrintWriter(socket.getOutputStream(), true);
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            connected = true;
            Gdx.app.log("Client", "Connected to server at " + host + ":" + port);

            startListening();

        } catch (Exception e) {
            Gdx.app.error("Client", "Error connecting to server", e);
            connected = false;
            if (this.messageListener != null) {
                this.messageListener.onDisconnected();
            }
        }
    }

    private void startListening() {
        listeningThread = new Thread(() -> {
            try {
                String serverMessage;
                while (connected && socket.isConnected() && (serverMessage = reader.readLine()) != null) {
                    // Gdx.app.log("Client", "Received: " + serverMessage);
                    if (messageListener != null) {
                        // Post to Gdx thread if UI updates are needed from here
                        Gdx.app.postRunnable(() -> messageListener.onMessageReceived(serverMessage));
                    }
                }
            } catch (IOException e) {
                if (connected) { // Log error only if we expected to be connected
                    Gdx.app.error("Client", "Error reading from server or connection closed", e);
                }
            } finally {
                handleDisconnect();
            }
        });
        listeningThread.start();
    }

    public void sendMessage(String message) {
        if (connected && writer != null) {
            writer.println(message);
            // Gdx.app.log("Client", "Sent: " + message);
        } else {
            Gdx.app.log("Client", "Not connected. Cannot send message.");
        }
    }

    private void handleDisconnect(){
        if (!connected) return; // Already handled
        connected = false;
        Gdx.app.log("Client", "Disconnected from server.");
        try {
            if (reader != null) reader.close();
            if (writer != null) writer.close();
            if (socket != null) socket.dispose();
        } catch (IOException e) {
            Gdx.app.error("Client", "Error closing client resources", e);
        }
        if (messageListener != null) {
             Gdx.app.postRunnable(() -> messageListener.onDisconnected());
        }
         if (listeningThread != null && listeningThread.isAlive()){
            listeningThread.interrupt(); // Attempt to stop the thread if it's stuck on readLine()
        }
    }

    public void disconnect() {
        handleDisconnect();
    }

    public boolean isConnected() {
        return connected;
    }
}
